package com.blogspot.sunserenity;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.regex.Pattern;

import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import com.blogspot.sunserenity.AsyncCipher.AsyncKey;

public class WindowForm extends JFrame{
	/**
	 * 
	 */
	private static final long serialVersionUID = 3330397306566017027L;
	JLabel jlInputSeq;
	JLabel jlOutputSeq;
	JLabel jlErrors;
	JTextField jtfErrors;
	JTextField jtfInputSeq;
	JTextArea jtaOutputSeq;
	JScrollPane jspTextOutput;
	JButton jbProcess;
	JButton jbLoadFile;
			
	private RSAAlgorithm rsa;
	private static StringBuilder outputConsoleText = new StringBuilder("");
		
	private void initRSA () {
		try {
			rsa = new RSAAlgorithm(1024);
			AsyncKey pk = rsa.getPublicKey();
			printLnToWindowOutput ("Public key is");
			printLnToWindowOutput ("Public exponenta: "+ pk.getExponenta().toString());
			printLnToWindowOutput ("Modulus: " + pk.getModulus().toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private static ArrayList<Integer> parseErrorPositions (String strPos) {
		ArrayList<Integer> positions = new ArrayList<Integer>();
		String[] strEPos = Pattern.compile (",[\\s]*").split(strPos.trim());
		if (strEPos.length > 0) {
			for (String sep : strEPos) {
				try {
					positions.add(Integer.parseInt(sep));
				} catch (Exception e) {
					if (!(e instanceof  NumberFormatException)) {
						System.err.println("Eception: " + e);
					}						
				}
			}
		}
		return positions;
	}
	
	public WindowForm (String title) {
		super (title);
		super.setSize (400,480);
		super.setResizable(false);
		getContentPane().setLayout(null);
		
		jlErrors = new JLabel("Errors");
			jlErrors.setBounds(10, 70, 370, 20);
		jtfErrors = new JTextField("1,2");
			jtfErrors.setBounds(10, 100, 370, 20);
			jtfErrors.setToolTipText("Type error positions separated by commas.");
		
		jlInputSeq = new JLabel("Input");
			jlInputSeq.setBounds(10, 10, 370, 20);
		
		jlOutputSeq = new JLabel("Output");
			jlOutputSeq.setBounds(10, 130, 370, 20);
		
		jtfInputSeq = new JTextField("EVERYDAYIMSHUFFLING");
			jtfInputSeq.setBounds(10, 40, 370, 20);
			jtfInputSeq.setToolTipText("Type message here.");
					
		jtaOutputSeq = new JTextArea("");
			jtaOutputSeq.setBounds(10, 160, 370, 160);
			jtaOutputSeq.setEditable(false);
		jspTextOutput = new JScrollPane(jtaOutputSeq);
			jspTextOutput.setBounds(10, 160, 370, 160);
		
		jbProcess = new JButton("Encrypt");
			jbProcess.setBounds(10, super.getSize().height -70, 80, 20);
			jbProcess.addActionListener (new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent arg0) {
					String sInput = jtfInputSeq.getText().trim();
					if (sInput.length() < 1) {
						printLnToWindowOutput("Nothing to encrypt.");
						return;
					}
					printLnToWindowOutput ("Started.");
					byte[]	
							original = sInput.getBytes(),
							cipher = rsa.encrypt(original, rsa.getPublicKey());
					printLnToWindowOutput("Clear cipher: " + new String (cipher));
					ArrayList<Integer> errorPos = parseErrorPositions (jtfErrors.getText());
					for (int pos : errorPos) {
						if (pos >= 0 && pos < cipher.length) {
							cipher[pos] ^= -1;
						}
					}
					printLnToWindowOutput("Cipher with errors: " + new String (cipher));
					byte[] recived = rsa.decrypt(cipher);
					String recivedStr = new String(recived);
					printLnToWindowOutput("Recived message: " + recivedStr);
					printLnToWindowOutput ("Finished.");
				}
			});
		/*	
		jbLoadFile = new JButton("Decrypt");
		jbLoadFile.setBounds(100, super.getSize().height -70, 150, 20);//-30
		jbLoadFile.addActionListener (new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				String sInput = jtfInputSeq.getText();
				if (sInput.length() < 1) {
					printLnToWindowOutput("Nothing to decrypt.");
					return;
				}
				printLnToWindowOutput("Starated.");
				byte[]	
						original = sInput.getBytes(),
						recived = rsa.decrypt(original);
				String recivedStr = new String(recived);
				printLnToWindowOutput("Recived message: " + recivedStr);
				printLnToWindowOutput ("Finished.");
			}
		});
		*/
		
		add (jlInputSeq, null);
		add (jtfInputSeq, null);
		add (jlErrors, null);
		add (jtfErrors, null);
		add (jlOutputSeq, null);
		add (jspTextOutput, null);
		add (jbProcess, null);
		//add (jbLoadFile, null);
		
		addWindowListener(new WindowAdapter() {
			public void windowClosing (WindowEvent we){
				System.exit(0);
			}
		});
		
		initRSA ();
		
		setVisible(true);
	}
	
	private void printLnToWindowOutput (String msg) {
		outputConsoleText.append(msg + "\n");
		if (jtaOutputSeq != null)
			jtaOutputSeq.setText(outputConsoleText.toString());
		else
			System.err.println("You should first init output component before print to.");
	}
	private void callWarning (String title, String msg) {
		JOptionPane.showMessageDialog(this, msg, title, JOptionPane.ERROR_MESSAGE);
	} 
}
